package com.cardgame.model.deck;

import com.cardgame.dao.ArchivalDao;
import com.cardgame.dao.CardDao;
import com.cardgame.dao.RoleDao;
import com.cardgame.model.card.*;
import com.cardgame.model.archival.Archival;
import com.cardgame.model.role.Role;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class DeckService implements IDeckService {
    private final Map<Integer, Deck> decks = new HashMap<>();
    private final AtomicInteger nextId = new AtomicInteger(1);
    private final Archival archival;
    private final CardDao cardDao;
    private final RoleDao roleDao;

    public DeckService(ArchivalDao archivalDao, CardDao cardDao, RoleDao roleDao) {
        this.archival = archivalDao.getArchival();
        this.cardDao = cardDao;
        this.roleDao = roleDao;
        for (Deck d : archival.getDecks()) {
            decks.put(d.getId(), d);
            nextId.set(Math.max(nextId.get(), d.getId() + 1));
        }
    }

    public List<Deck> getAllDecks() {
        return new ArrayList<>(decks.values());
    }

    public Deck getDeck(Integer id) {
        return decks.get(id);
    }

    public List<Role> getOwnedRoles() {
        List<Integer> ownedRoleIds = archival.getRoles();
        List<Role> allRoles = roleDao.getAllRoles();
        return allRoles.stream()
                .filter(role -> ownedRoleIds.contains(role.getId()))
                .collect(Collectors.toList());
    }

    public List<Card> getOwnedCards() {
        Map<Integer, Integer> ownedCardMap = archival.getCards();
        List<Card> cards = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : ownedCardMap.entrySet()) {
            int id = entry.getKey();
            Card card = cardDao.getCardById(id);
            for (int i = 0; i < entry.getValue(); i++) {
                cards.add(card);
            }
        }
        return cards;
    }

    public Deck saveDeck(Integer id, String name, Map<Integer, Integer> cards, Integer leaderRoleId,
            boolean isPlayerControlled) {
        Map<Integer, Integer> ownedCards = archival.getCards();
        if (leaderRoleId == null){
            throw new IllegalArgumentException("请选择角色");
        }
        int maxCards = 20;
        if (isPlayerControlled) {
            int totalCards = cards.values().stream().mapToInt(Integer::intValue).sum();
            if (totalCards > maxCards) {
                throw new IllegalArgumentException("总卡牌数量超过上限: " + totalCards + "/" + maxCards);
            }
            for (Map.Entry<Integer, Integer> entry : cards.entrySet()) {
                int cardId = entry.getKey();
                int count = entry.getValue();
                int owned = ownedCards.getOrDefault(cardId, 0);
                if (count > owned) {
                    throw new IllegalArgumentException("卡牌ID " + cardId + " 数量超过拥有上限: " + count + "/" + owned);
                }
            }
        }

        Deck deck;
        if (id == null) {
            id = nextId.getAndIncrement();
            deck = new Deck(name, leaderRoleId, cards);
            deck.setPlayerControlled(isPlayerControlled);
        } else {
            deck = decks.get(id);
            if (deck == null) {
                throw new IllegalArgumentException("卡组不存在");
            }
            deck.setName(name);
            deck.setCards(cards);
            deck.setLeaderRoleId(leaderRoleId);
            deck.setPlayerControlled(isPlayerControlled);
        }
        decks.put(id, deck);
        archival.setDecks(new ArrayList<>(decks.values()));
        return deck;
    }

    public void deleteDeck(Integer id) {
        if (!decks.containsKey(id)) {
            throw new IllegalArgumentException("卡组不存在");
        }
        decks.remove(id);
        archival.setDecks(new ArrayList<>(decks.values()));
    }
}
